﻿using System;

namespace Effects.Effects.Tools
{
    /// <summary>
    ///  Delay line with adjustable delay time.
    /// </summary>
    /// <remarks> 
    ///  This class is little bit tweaked FeedbackConstantDelayLine, so delay time can be adjustable by user. 
    ///  The length of FeedbackConstantDelayLine is now the maximal delay length and delay length can be set anywhere between zero and this maximum
    /// </remarks>
    public class VariableDelayLine : FeedbackConstantDelayLine
    {
        /// <summary>
        ///  Real delay length in samples
        /// </summary>
        protected int delayLength;

        /// <summary>
        ///  Gets or sets the delay time.
        /// </summary>
        public int DelayLength
        {
            get { return delayLength; }
            set
            {
                if (value >= 0 && value <= length)
                    delayLength = value;
            }
        }

        /// <summary>
        ///  Gets or sets the feedback parameter.
        /// </summary>
        public double Feedback
        {
            get { return feedback; }
            set
            {
                if (value >= 0 && value <= 1)
                {
                    feedback = value;
                    feedback_1 = 1 - feedback;
                }
            }
        }


        /// <summary>
        ///  Creates new VariableDelayLine with given parameters
        /// </summary>
        /// <param name="length"> Maximal delay length </param>
        /// <param name="feedback"> Feedback parameter from range 0-1 </param>
        public VariableDelayLine(int length, double feedback) : base(length, feedback) { }

        /// <summary>
        ///  Creates new VariableDelayLine with given parameters
        /// </summary>
        /// <param name="time"> Maximal delay length </param>
        /// <param name="sampleRate"> Sample rate of incoming samples </param>
        /// <param name="feedback"> Feedback parameter from range 0-1 </param>
        public VariableDelayLine(double time, int sampleRate, double feedback) : base(time, sampleRate, feedback) { }

        /// <summary>
        ///  Implemented step method. Takes input and returns output.
        /// </summary>
        /// <param name="sample"> Input sample </param>
        /// <returns> Modified output of the delay line </returns>
        public override double Step(double sample)
        {
            double ret = Top;

            //data[index] = feedback * ret + feedback_1 * sample;
            
            data[index] = feedback * ret +  sample;
            index--;
            if (index < 0)
                index += length;
            return ret;
        }


        /// <summary>
        ///  Returns top of the delay line.
        /// </summary>
        public override double Top
        {
            get
            {
                return data[(index + delayLength) % length];
            }
        }
        
    }
}